#pragma once
#include "../http/HttpRequest.h"
#include "../http/HttpResponse.h"
#include "RouterHandler.h"
#include <unordered_map>
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <regex>

namespace http
{
    namespace router
    {
        class Router
        {
        public:
            // 选择注册对象式的路由处理器还是注册回调函数式的处理器取决于处理器执行的复杂程度
            // 如果是简单的处理可以注册回调函数，否则注册对象式路由处理器(对象中可封装多个相关函数)
            // 二者注册其一即可
            using HandlerPtr = std::shared_ptr<RouterHandler>;                                // 对象式路由处理器指针类型,用于存储路由处理器
            using HandlerCallback = std::function<void(const http::HttpRequest &, http::HttpResponse &)>; // 回调函数式路由处理器类型,用于存储路由处理器回调函数

            // 路由键，用于匹配路由（请求方法+路径）
            struct RouteKey
            {
                HttpRequest::Method method;
                std::string path;
                // 重载==运算符，用于比较两个路由键是否相等
                bool operator==(const RouteKey &other) const
                {
                    return method == other.method && path == other.path;
                }
            };

            // 路由键哈希函数，用于将路由键映射到哈希表的索引
            struct RouteKeyHash
            {
                // 异或运算符，用于将两个哈希值组合起来
                // 问题是两个值非常接近，导致哈希冲突或者哈希值分散不均匀
                //  size_t operator()(const RouteKey& key) const{
                //      return std::hash<int>()(static_cast<int>(key.method)) ^ std::hash<std::string>()(key.path);
                //  }
                // 使用std::hash<int>()和std::hash<std::string>()分别计算方法和路径的哈希值
                // 然后使用乘法运算符将两个哈希值组合起来
                // 这种方法可以减少哈希冲突，提高哈希表的性能
                size_t operator()(const RouteKey &key) const
                {
                    size_t methodHash = std::hash<int>()(static_cast<int>(key.method));
                    size_t pathHash = std::hash<std::string>()(key.path);
                    return methodHash * 17 + pathHash; // 17是质数，用于减少哈希冲突
                }
            };

            // 注册对象式路由处理器
            void registerHandler(const std::string &path, HttpRequest::Method method, HandlerPtr handler);

            // 注册回调函数形式的路由处理器
            void registerCallback(const std::string &path, HttpRequest::Method method, const HandlerCallback &callback);

            // 注册正则表达式路由处理器
            void addRegexHandler(const std::string &path, HttpRequest::Method method, HandlerPtr handler)
            {
                std::regex pathRegex(path);
                _regexHandlers.emplace_back(method, pathRegex, handler);
            }

            // 注册正则表达式路由处理器,回调函数式路由处理器
            void addRegexCallback(const std::string &path, HttpRequest::Method method, const HandlerCallback &callback)
            {
                std::regex pathRegex(path);
                _regexCallbacks.emplace_back(method, pathRegex, callback);
            }

            // 处理请求
            bool route(const HttpRequest &request, HttpResponse &response);

        private:
            // 将路径转换为正则表达式
            // std::regex(R"(/:([^/]+))")：这是一个正则表达式，用于匹配路径中的动态参数部分。
            // 具体来说：
            //  /：表示路径的分隔符。
            //  :：表示后面跟着的是一个动态参数。
            //  (：表示捕获组开始。
            //  [^/]+：这是一个捕获组，表示匹配一个或多个非斜杠字符（即参数的值）。
            //  )：表示捕获组结束。
            std::regex convertPathToRegex(const std::string &path)
            {
                std::string regexPath = "^" + std::regex_replace(path, std::regex(R"(/:([^/]+))"), R"(/([^/]+))") + "$";
                return std::regex(regexPath);
            }
            // 提取路径参数,smatch是正则表达式匹配结果
            void extractPathParams(const std::smatch &match, HttpRequest &request)
            {
                // 遍历匹配结果，设置路径参数 从1开始匹配 因为0是整个匹配结果
                for (size_t i = 1; i < match.size(); ++i)
                {
                    // param1,param2,param3...
                    request.setPathParams(("param" + std::to_string(i)), match[i].str());
                }
            }

            // 对象式路由处理器，封装了请求方法和路径正则表达式
            struct RouteHandlerObj
            {
                HttpRequest::Method _method;
                std::regex _pathRegex;
                HandlerPtr _handler;
                RouteHandlerObj(HttpRequest::Method method, const std::regex &pathRegex, HandlerPtr handler)
                    : _method(method), _pathRegex(pathRegex), _handler(std::move(handler)) {}
            };
            // 回调函数式路由处理器，封装了请求方法和路径正则表达式
            struct RouteCallbackObj
            {
                HttpRequest::Method _method;
                std::regex _pathRegex;
                HandlerCallback _callback;
                RouteCallbackObj(HttpRequest::Method method, const std::regex &pathRegex, HandlerCallback callback)
                    : _method(method), _pathRegex(pathRegex), _callback(std::move(callback)) {}
            };

            std::unordered_map<RouteKey, HandlerPtr, RouteKeyHash> _handlers; // 对象式路由表，存储路由信息,用路由键作为键，处理器指针作为值
            std::unordered_map<RouteKey, HandlerCallback, RouteKeyHash> _callbacks;         // 回调函数式路由表，存储路由信息,用路由键作为键，回调函数作为值    
            std::vector<RouteHandlerObj> _regexHandlers;                      // 正则表达式路由表，存储路由信息,用正则表达式作为键，处理器指针作为值
            std::vector<RouteCallbackObj> _regexCallbacks;                    // 正则表达式路由表，存储路由信息,用正则表达式作为键，回调函数作为值
        };
    }
}
